<?php


namespace App\Service\client;


use App\Common\RedisUtils;
use App\Common\Res;
use App\Common\SendMsgUtils;
use App\Common\StringUtils;
use App\Constants\ConstCode;
use App\Constants\ErrorCode;
use App\Model\form\MessageTalkTrait;
use App\Model\form\WeworkAccountTrait;
use App\Model\form\WeworkFriendTrait;
use App\Model\FriendTalk;
use App\Model\MessageTalk;
use App\Model\TaskMobile;
use App\Model\WeworkFriend;
use App\Request\client\TalkRequest;
use Hyperf\DbConnection\Db;
use Hyperf\Utils\ApplicationContext;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class friendService
{
    use StringUtils, Res, RedisUtils, SendMsgUtils,
        WeworkFriendTrait, WeworkAccountTrait, MessageTalkTrait;

    /**
     * 客户端上传好友聊天信息到服务端
     * @param $fd
     * @param array $params
     * @return array
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function appUploadTalkInfo($fd, array $params): array
    {
        //ApplicationContext::getContainer()->get(TalkRequest::class)->validated($params['data'], __FUNCTION__);
        $params_data = $params['data'];
        if (empty($params_data['mobile']) && empty($params_data['nickname']))
            return $this->Error(ErrorCode::ERROR, '好友手机号码和昵称不能同时为空');
        Db::beginTransaction();
        try {
            /*根据token查询redis是否存在数据*/
            $token = trim($params['token']);
            $deviceInfo = $this->hGet($this->hKey, $token);
            $deviceArr = json_decode($deviceInfo, true);
            $account = $this->getWeworkAccount(['marketUserId' => $deviceArr['marketUserId']]);
            if (!empty($account)) {
                $where = function ($query) use ($params_data, $account) {
                    if (!empty($params_data['mobile']))
                        $query->where('mobile', $params_data['mobile']);
                    if (!empty($params_data['nickname']))
                        $query->where('nickname', $params_data['nickname']);
                    $query->where('account_id', $account['id']);
                };
                $workFriend = $this->getWeworkFriendInfo($where);
                if (empty($workFriend)) {
                    $params_data['account_id'] = $account['id'];
                    $workFriend = $this->createFriendInfo($params_data);
                }
                if (!empty($workFriend)) {
                    /*需判断当通过好友还未来得及同步信息，就发送消息的情况*/
                    /*根据状态修改对话状态和好友状态*/
                    if ($params_data['type'] == 1011 && $params_data['friend_status'] != 1) {
                        $workFriendInfo = $this->getWeworkFriendInfo(['id' => $workFriend['id']]);
                        $workFriendInfo->status = $params_data['friend_status'];
                        $workFriendInfo->save();
                        $friendTalkData['status'] = 2;
                    }
                    /*新增一条聊天对话*/
                    $friendTalkData = [
                        'userSex' => !empty($workFriend['sex']) ? $workFriend['sex'] : 0,
                        'userNickName' => !empty($workFriend['nickname']) ? $workFriend['nickname'] : $workFriend['bookname'],
                        'userId' => $workFriend['userId'],
                        'account_id' => $workFriend['account_id'],
                    ];
                    if (!empty($workFriend['mobile']))
                        $friendTalkData['uerMobileNo'] = $workFriend['mobile'];
                    $map = function ($query) use ($params_data, $account) {
                        if (!empty($params_data['mobile']))
                            $query->where('uerMobileNo', $params_data['mobile']);
                        if (!empty($params_data['nickname']))
                            $query->where('userNickName', $params_data['nickname']);
                        $query->where('account_id', $account['id']);
                    };
                    $friendTalk = FriendTalk::where($map)->first();
                    if (empty($friendTalk)) {
                        FriendTalk::create($friendTalkData);
                    }
                    /*新增聊天记录*/
                    //$content = $this->getContentByType($params_data['type'], $params_data['content']);
                    $content = $params_data['content'];
                    $add_time = intval($params_data['timestamp']);
                    $messageId = MessageTalk::insertGetId([
                        'content' => $content,
                        'userId' => $workFriend['userId'],
                        'account_id' => $workFriend['account_id'],
                        'direction' => 1,
                        'type' => $params_data['type'],
                        'created_at' => date("Y-m-d H:i:s", time()),
                        'add_time' => $add_time,
                    ]);
                    /*加入redis用于消息发送*/
                    $message['id'] = $messageId;
                    $message['content'] = $content;
                    $message['userId'] = $workFriend['userId'];
                    $message['marketUserId'] = $this->getWeworkAccountMarketUserId(['id' => $workFriend['account_id']]);
                    $message['operation_user_id'] = $account['user_id'];
                    $message['direction'] = 1;
                    $message['isRoomMsg'] = false;
                    $message['type'] = $params_data['type'];
                    $message['created_at'] = date("Y-m-d H:i:s", time());
                    $message['add_time'] = $add_time;
                    $message['is_send'] = 0;
                    /*判断有没有消息*/
                    $messageKey = $this->getMessageKey();
                    $message['key'] = $messageKey;
                    $res = $this->zAdd('messageKey', $add_time, $messageKey);
                    if ($res) {
                        $this->hSet('message', $messageKey, str_replace("\/", "/", json_encode($message, 256)));
                    }
                    $data['status'] = 1;
                    $data['msg'] = '聊天信息上传成功';
                } else {
                    /*发送登录信息*/
                    $data['status'] = 0;
                    $data['msg'] = '聊天信息上传失败';
                }
            } else {
                /*发送登录信息*/
                $data['status'] = 0;
                $data['msg'] = '聊天信息上传失败';
            }
            $result = $this->sendAppUploadTalkInfo($fd, $data);
            Db::commit();
            return $this->Success('聊天信息处理成功', $result);
        } catch (\Throwable $ex) {
            Db::rollBack();
            $data['status'] = 0;
            $data['msg'] = $ex->getMessage();
            $result = $this->sendAppUploadTalkInfo($fd, $data);
            return $this->Error(ErrorCode::ERROR, '聊天信息处理失败' . $ex->getMessage());
        }
    }

    /**
     *根据聊聊天信息生成好友
     */
    function createFriendInfo(array $params): array
    {
        if (!empty($params['nickname']))
            $data['nickname'] = $params['nickname'];
        if (!empty($params['describe']))
            $data['remark'] = $params['describe'];
        if (!empty($params['mobile']))
            $data['mobile'] = $params['mobile'];
        if (!empty($params['sex']))
            $data['sex'] = $params['sex'];
        if (!empty($params['friend_status']) && $params['friend_status'] != 1)
            $data['status'] = $params['friend_status'];
        $data['bookname'] = $this->getRandomName();
        $data['userId'] = $this->getRandomUserId();
        $data['account_id'] = $params['account_id'];
        $data['addTime'] = time();
        $workFriend = WeworkFriend::create($data);
        return !empty($workFriend) ? $workFriend->toArray() : [];

    }


    /**
     *检查最后一条消息类型
     */
    function appGetFriendLastMessage($fd, array $params): array
    {
        /*根据账号好友手机号查找该好友最后一条消息，类型，如果是图片*/
        //ApplicationContext::getContainer()->get(TalkRequest::class)->validated($params['data'], __FUNCTION__);
        $params_data = $params['data'];
        if (empty($params_data['mobile']) && empty($params_data['nickname']))
            return $this->Error(ErrorCode::ERROR, '好友手机号码和昵称不能同时为空');
        /*根据token查询redis是否存在数据*/
        $token = trim($params['token']);
        $deviceInfo = $this->hGet($this->hKey, $token);
        $deviceArr = json_decode($deviceInfo, true);
        $data['type'] = 0;
        $data['content'] = '';
        $data['mobile'] = !empty($params_data['mobile']) ? $params_data['mobile'] : '';
        $data['nickname'] = !empty($params_data['nickname']) ? $params_data['nickname'] : '';
        $data['count'] = 0;
        $data['status'] = 0;
        if (!empty($deviceArr)) {
            try {
                $account = $this->getWeworkAccount(['marketUserId' => $deviceArr['marketUserId']]);
                if (!empty($params_data['mobile'])) {
                    $friend = $this->getWeworkFriend(['mobile' => $params_data['mobile'], 'account_id' => $account['id']]);
                } else {
                    $friend = $this->getWeworkFriend(['nickname' => $params_data['nickname'], 'account_id' => $account['id']]);
                }
                if (!empty($account) && !empty($friend)) {
                    $data['msg'] = '获取最新消息成功';
                    $data['status'] = 1;
                    $lastMessage = $this->getLastOneMessage(['userId' => $friend['userId'], 'account_id' => $account['id'], 'direction' => 1]);
                    if (!empty($lastMessage)) {
                        /*如果是图片，则查询最后开始有几张图片，和最新一条文字消息*/
                        $excludedTypes = [
                            ConstCode::TEXT_TYPE_5003,
                            ConstCode::TEXT_TYPE_5006,
                            ConstCode::TEXT_TYPE_101,
                        ];
                        if (in_array($lastMessage['type'], $excludedTypes)) {
                            /*如果最后一条消息是图片，则查询最近的一条文本消息**/
                            $where = function ($query) use ($account, $friend, $excludedTypes) {
                                $query->where('userId', $friend['userId']);
                                $query->where('account_id', $account['id']);
                                $query->where('direction', 1);
                                $query->whereNotIn('type', $excludedTypes);
                            };
                            $lastTxtMessage = $this->getLastOneMessage($where);
                            if (!empty($lastTxtMessage)) {
                                $data['content'] = $lastTxtMessage['content'];
                                /*如果文本存在则查询文本下面的图片数量*/
                                $map = function ($query) use ($account, $friend, $excludedTypes, $lastTxtMessage) {
                                    $query->where('userId', $friend['userId']);
                                    $query->where('account_id', $account['id']);
                                    $query->where('direction', 1);
                                    $query->where('id', '>', $lastTxtMessage['id']);
                                    $query->whereIn('type', $excludedTypes);
                                };
                            } else {
                                /*如果文本不存在则查询图片数量*/
                                $map = function ($query) use ($account, $friend, $excludedTypes, $lastTxtMessage) {
                                    $query->where('userId', $friend['userId']);
                                    $query->where('account_id', $account['id']);
                                    $query->where('direction', 1);
                                    $query->whereIn('type', $excludedTypes);
                                };
                            }
                            $data['count'] = $this->getLastImageCount($map);
                        } else {
                            $data['content'] = $lastMessage['content'];
                        }
                        $data['type'] = $lastMessage['type'];
                    }
                }
                $result = $this->sendAppGetFriendLastMessage($fd, $data);
                return $this->Success('聊天信息处理成功', $data);
            } catch (\Throwable $ex) {
                $data['msg'] = $ex->getMessage();
                $result = $this->sendAppGetFriendLastMessage($fd, $data);
                return $this->Error(ErrorCode::ERROR, '获取最新消息失败' . $ex->getMessage());
            }
        }
        $data['msg'] = '获取最新消息失败设备信息有误';
        $result = $this->sendAppGetFriendLastMessage($fd, $data);
        return $this->Error(ErrorCode::ERROR, '获取最新消息失败设备信息有误');
    }

}